import json


class StateInterface:
    job_id = None
    name_first = None
    name_second = None
    logger = None
    state_source = None
    
    """Interface"""
    def write_key_log(self, code, *, msg=None, data: dict=None):
        # format:
        #  <name>||<asctime>||<process>||<levelname>||<filename>-><module>-><funcName> <lineno>||K||SpiderKeyLog||<msg>
        #    error_msg:  SpiderKeylog||<msg>
        # format:
        #  <name>||<asctime>||<process>||<levelname>||<filename>-><module>-><funcName> <lineno>||K||SpiderKeyLog||<msg>
        #    error_msg:  SpiderKeylog||<msg>
        if code not in StateEnum.all_state_codes():
            raise ValueError('{} not supported'.format(code))

        _data = self._data_pack(code)

        if msg:
            _data.update({'msg': msg})
        if data:
            _data.update({'data': data})
        _str = 'SpiderKeyLog||{}'.format(json.dumps(_data))
        self.logger.info(_str)
        
    def _data_pack(self, code):
        return {
            'job_id': self.job_id,
            'name_first': self.name_first,
            'name_second': self.name_second,
            'source_type': self.state_source,
            'code': code,
        }


class StateEnum:
    """
    E: 1-127; error类型
    
    I: 127- ; 非error类型
    """
    # :code                          :meaning                           :owner         :cal        data
    E_HOME_PAGE = 1                 # 访问首页失败；						爬虫打印        累加		   	N/A
    E_EXTRACT_DETAIL = 2            # 提取详情页失败；						爬虫打印        累加			N/A
    E_ACCESS_DETAIL = 3             # 访问详情页失败；						爬虫打印        累加			N/A
    E_EXTRACT_PAGE = 4              # 提取翻页信息失败；					爬虫打印        累加			N/A
    E_ACCESS_PAGE = 5               # 访问翻页失败；						爬虫打印        累加			N/A

    E_PARSE_ERROR = 6               # 解析异常；						    框架打印        累加			N/A
    E_PARSE_RESULT_INVALID = 7      # 解析结果不合法；						框架打印        累加			N/A
    E_EMPTY_SEED = 8                # 未获取到种子，						框架打印        累加			N/A
    E_SEED_RESULT_EMPTY = 9         # 按种子未搜索到数据；					爬虫打印        累加			N/A
    E_HC_ERR_200 = 10               # http code 是 200 但是页面错误；		爬虫打印        累加			N/A

    E_SOURCE_SAVE = 20              # 原文存储失败；						框架打印        累加			N/A
    E_RESULT_SAVE = 21              # 结果存储失败；                      框架打印        累加			N/A

    I_TOTAL_COUNT = 128             # 总数；							    爬虫打印        max			{'total_count': 10000, 'ts': 1555555555}
    I_NEW_COUNT = 129               # 增量；						        爬虫打印        max			{'new_count': 5555, 'ts': 155555555}
    I_FINISH_NO_OUTPUT = 130        # 完全没有输出；						框架打印        N/A			{'item_scraped_count': 0}
    I_FINISH_WITH_OUTPUT = 131      # 有输出；						    框架打印        N/A			{'item_scraped_count': 1}
    I_REQUEST_COUNT = 132           # 请求数；						    框架打印        累加			{'request_count': 5555}
    I_RESPONSE_COUNT = 133          # 响应数；						    框架打印        累加			{'response_count': 5555}
    I_SEED_COUNT = 134              # 消耗种子数；						框架打印        累加			{'seed_count': 5555}
    I_PAGE_COUNT = 135              # 总页数；						    爬虫打印        N/A			{'page_count': 5555}
    I_ITEM_COUNT_PER_PAGE = 136     # 每页条数；						    爬虫打印        N/A			{'count_per_page': 5555}
    I_START = 137                   # 启动；                             框架打印        N/A			N/A
    I_STOP = 138                    # 停止；                             框架打印        N/A			N/A
    I_SEED_STATE_CHANGE = 139       # 种子状态变动；                       框架打印        N/A			N/A
    I_LAST_ITEM = 140               # 最近一条数据信息；                    爬虫打印        N/A			{'content': “XXXXXXXXXXX”}
    
    _all_state_enum_codes = []
    
    @classmethod
    def all_state_codes(cls):
        if not cls._all_state_enum_codes:
            for i in dir(cls):
                if (i.startswith('E_') or i.startswith('I_')) and isinstance(getattr(cls, i), int):
                    cls._all_state_enum_codes.append(getattr(cls, i))
        return cls._all_state_enum_codes


class StateSourceEnum:
    """
    Source 类型
    """
    SAT_SRC_E_P = 1            # 解析
    SAT_SRC_E_C = 2            # 抓取
    SAT_SRC_E_A = 3            # 混合


# Test code
if __name__ == '__main__':
    print(StateEnum.all_state_codes())